package xian.woniu.util;

import io.jsonwebtoken.*;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


/**
 * 这是一个JWtUtils的工具类。 里面封装了创建，校验，获取 Jwt  的三个方法。
 */

public class JwtUtils {
    /**
     * 私钥密码，保存在服务器，客户端是不会知道密码的，以防止被攻击
     */
    private static final String SECRET = "mysecret";
    /**
     * 加密方式HS256
     */
    private static final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

    /**
     * 对密钥进行加密
     *
     * @return
     */
    private static Key getkey() {
        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(SECRET);
        return new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
    }

    /**
     * 生成Token
     * <p>
     * JWT分成3部分：1.头部（header)，2.载荷，3.签证（signature)
     * <p>
     * 加密后这3部分密文的字符位数为：
     * 1.头部（header)：36位，Base64编码
     * 2.载荷（payload)：没准，BASE64编码
     * 3.签证（signature)：43位，将header和payload拼接生成一个字符串，
     * 使用HS256算法和我们提供的密钥（secret,服务器自己提供的一个字符串），
     * 对str进行加密生成最终的JWT
     *
     * @return
     * @throws Exception
     */
    public static String createToken(String username, int expireSeconds) {

        // 组合header
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");
        JwtBuilder builder = Jwts.builder();
        builder.setHeaderParams(map);

        // 有效荷载，存放了用户名
        builder.claim("username", username);

        // 生成第三部分
        builder.signWith(SignatureAlgorithm.HS256, getkey());

        // 签发时间
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);

        // 设置过期时间
        if (expireSeconds >= 0) {
            long expMillis = nowMillis + (expireSeconds + 2) * 1000;
            Date expDate = new Date(expMillis);
            builder.setExpiration(expDate); // 过期时间
        }
        builder.setIssuedAt(now);

        String token = builder.compact();
        return token;
    }

    /**
     * 解密Token查看其是否合法
     *
     * @param token
     * @return
     */
    public static boolean verifyToken(String token) {
        Claims body = null;
        try {
            body = Jwts.parser().setSigningKey(getkey()).parseClaimsJws(token).getBody();
        } catch (ExpiredJwtException e) {
            e.printStackTrace();
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return body!= null;
    }

    public static String getUsername(String token) {
        Claims body = null;
        try {
            body = Jwts.parser().setSigningKey(getkey()).parseClaimsJws(token).getBody();
        } catch (ExpiredJwtException e) {
            throw new RuntimeException("超时", e);
        } catch (Exception e) {
            throw new RuntimeException("未知错误", e);
        }
        return (String) body.get("username");
    }
}